
#include "ByteFIFO.h"
#include "cc_pub.h"

/********* interior	define ***********/
#define CFG_RWLOCK_CHECK 

#define LLOG
#define LLOG_ERR
#define LLOG_MARK
#include "llog.h"

#ifdef	CFG_STATIC_BUF_ALLOCATE
#define L_MALLOC 	SMalloc
#define L_FREE(A) 	LLOG_ERR()
#else
#define L_MALLOC 	malloc
#define L_FREE(A)	free(A)
#endif
//

/********* interior  struct **********/
struct CC_Byte_FIFO_V4{
    uint8_t* pBuf;
	uint32_t BufSz;	// IndexMax

	uint32_t wIndex;         
    uint32_t rIndex;
	
	uint8_t  RWLock;
};


/********** global val ***************/

/******* local function **************/

/******* TODO ************************/


//=============
#ifdef CFG_BYTE_FIFO
void BFIFO_ShowObj(tBFIFO* pObj){
    LLOG("BFIFO\n");
	LLOG("pBuf	 =[%x]\n",pObj->pBuf	);
	LLOG("BufSz	 =[%d]\n",pObj->BufSz	);
	LLOG("wIndex =[%d]\n",pObj->wIndex	);
	LLOG("rIndex =[%d]\n",pObj->rIndex	);
	LLOG("RWLock =[%x]\n",pObj->RWLock	);
	
	LLOG("RecvNum =[%d]\n",BFIFO_GetRecvNum(pObj));
}

/* static int BFIFO_Init(tBFIFO* pObj ,uint32_t BufSz, uint8_t* pBuf){ 
    
	int ret = RET_ERR;
    int i;
	uint8_t* ptmp;
	
	if(pObj == NULL || pBuf == NULL || BufSz == 0){
		LLOG_ERR();
		return ret;
	}
	ret = RET_OK;
	
	ptmp=(uint8_t*)pObj;
	for(i=0;i<sizeof(tBFIFO);i++){
		ptmp[i]=0;
	}
	pObj->pBuf 	= pBuf;
	pObj->BufSz = BufSz; 
	
    return ret;   
} */

tBFIFO* BFIFO_Create(uint32_t BufSz){
	
	tBFIFO* ptmp=NULL;
	uint8_t* 	pBuf=NULL;
	
	if(BufSz == 0){
		return ptmp;
	}
	
	ptmp=(tBFIFO*)L_MALLOC(sizeof(tBFIFO));
	if(ptmp == NULL){
		LOG_ERR();
		return ptmp;
	}
	pBuf=L_MALLOC(BufSz);
	if(pBuf == NULL){
		L_FREE(ptmp);
		LOG_ERR();
		return NULL;
	}	

	MEMSET(ptmp,0,sizeof(tBFIFO));
	ptmp->pBuf 	= pBuf;
	ptmp->BufSz = BufSz; 
	
	// BFIFO_Init(ptmp,BufSz,pBuf);

	return ptmp;
}

uint32_t BFIFO_Write(tBFIFO* pObj,uint32_t dLen, uint8_t* pPkg){
	
	uint8_t* pBuf;
	
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t PartNum;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
    
	CopySz=0;
    if( (pObj== NULL) || (pPkg == NULL) || (dLen == 0) ){
        return CopySz;
    }
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock=1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->BufSz;
	
	LOOP_CALC(CopySz,wIndex,rIndex,LoopSz);		 // empty 
	CopySz -= 1;
	
	
    if(CopySz == 0){
		pObj->RWLock = 0;
		return CopySz;
	}
	
	pBuf = pObj->pBuf;
	CopySz=(CopySz > dLen)? dLen: CopySz; 
	if(CopySz ==1){		
		pBuf[wIndex++] = pPkg[0];
	}
	else{
		
		PartNum= LoopSz-wIndex; 
		if( CopySz > PartNum)
		{
			for(i=0;i<PartNum;i++){
				pBuf[wIndex++]=pPkg[i];
			}
			wIndex = 0;
			for(;i<CopySz;i++){
				pBuf[wIndex++]=pPkg[i];
			}
		}
		else{ 
			for(i=0;i<CopySz;i++){
				pBuf[wIndex++]=pPkg[i];
			}
		}
		
	}
	wIndex = (wIndex < LoopSz)?wIndex:0;
	
	pObj->wIndex=wIndex;
	pObj->RWLock=0;
    return CopySz;
	
}

uint32_t BFIFO_Read(tBFIFO* pObj,uint32_t readNum, uint8_t* pRBuf){

	uint8_t* pBuf;
	
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t PartNum;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
    
	CopySz=0;
    if( (pObj== NULL) || (pRBuf == NULL) || (readNum == 0) ){
        return CopySz;
    }
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){	
		return CopySz;
	}
	#endif
	pObj->RWLock=1; 
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->BufSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz); // RecvNum 
	
    if(CopySz == 0){
		// LLOG_MARK();
		pObj->RWLock = 0;
		return CopySz;
	}
	
	pBuf = pObj->pBuf;
	CopySz=(CopySz > readNum)?readNum: CopySz; 
	
	if(CopySz == 1){
		pRBuf[0] = pBuf[rIndex++];
	}
	else{
		PartNum= LoopSz-rIndex; 
		// if( (rIndex > wIndex) && (CopySz > PartNum) )
		if(CopySz > PartNum)
		{
			for(i=0;i<PartNum;i++){
				pRBuf[i] = pBuf[rIndex++];
			}
			rIndex = 0; // rIndex = (rIndex < LoopSz)?rIndex:0;
			for(;i<CopySz;i++){
				pRBuf[i] = pBuf[rIndex++];
			}
		}
		else{
			for(i=0;i<CopySz;i++){
				pRBuf[i] = pBuf[rIndex++];
			}
		}
	}
	rIndex = (rIndex < LoopSz)?rIndex:0;
	
	pObj->rIndex = rIndex;
	pObj->RWLock = 0;
    return CopySz;
	
}

uint32_t BFIFO_GetRecvNum(tBFIFO* pObj){

	uint8_t* pBuf;
	
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t PartNum;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
    
	CopySz=0;
    if( pObj== NULL ){
        return CopySz;
    }
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; 
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->BufSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);
	
	pObj->RWLock = 0;
	return CopySz;
}

int BFIFO_Reset(tBFIFO* pObj){
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){
		return RET_ERR;
	}
	#endif
	pObj->RWLock = 1; 	
	pObj->wIndex = 0;
	pObj->rIndex = 0;
	
	MEMSET(pObj->pBuf,0,pObj->BufSz);
	
	pObj->RWLock = 0;
	
	return RET_OK;
}

#endif

